home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / metamail / contrib / mms / mmsserver.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-05-19  |  19.1 KB  |  801 lines

  1. /*////////////////////////////////////////////////////////////////////////
  2. Copyright (c) 1992 Electrotechnical Laboratry (ETL)
  3.  
  4. Permission to use, copy, modify, and distribute this material 
  5. for any purpose and without fee is hereby granted, provided 
  6. that the above copyright notice and this permission notice 
  7. appear in all copies, and that the name of ETL not be 
  8. used in advertising or publicity pertaining to this 
  9. material without the specific, prior written permission 
  10. of an authorized representative of ETL.
  11. ETL MAKES NO REPRESENTATIONS ABOUT THE ACCURACY OR SUITABILITY 
  12. OF THIS MATERIAL FOR ANY PURPOSE.  IT IS PROVIDED "AS IS", 
  13. WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES.
  14. /////////////////////////////////////////////////////////////////////////
  15. Content-Type: program/C; charset=US-ASCII
  16. Program:      mmsserver.c  (metamail server)
  17. Author:       Yutaka Sato <ysato@etl.go.jp>
  18. Description:
  19.      This is a program that allows programs to compose/decompsea
  20.      a MIME-format mail with the commands via socket.
  21. History:
  22.   v0.0  92.04.21  created a small prototype
  23.     930505    fixed JLE's scanf("%[^\377]") problem
  24. ///////////////////////////////////////////////////////////////////////*/
  25. typedef int (*IFUNCP)();
  26.  
  27. char *MMS_versionNO = "0.6.4";
  28. char *MMS_versionDate = "20 May. 1993";
  29.  
  30. MMS_E_version(ac,av,in,out){
  31.     fprintf(out,"%s\n",MMS_versionNO);
  32. }
  33. IFUNCP MMS_E_VERSION = MMS_E_version;
  34.  
  35. /*/////////////////////////////////////////////////////////////////////*/
  36.  
  37. MMS_E_server(ac,av,in,out)
  38.     char *av[];
  39. {
  40.     MMS_server(ac,av);
  41. }
  42. IFUNCP MMS_E_SERVER = MMS_E_server;
  43.  
  44. int MMS_ACCESS;
  45.  
  46. /*//////////////////////////////////////////////////////////////////////*/
  47. #include <stdio.h>
  48. #include <sys/param.h>
  49. #include <pwd.h>
  50. #include <signal.h>
  51.  
  52. char *getenv(),*index(),*rindex();
  53. FILE *tmpfile();
  54. FILE *MMS_synthWriteFile();
  55. char *MMS_getline();
  56. #define MMS_COMMANDIN stdin
  57. struct passwd *MMS_user();
  58. FILE *MMS_getbody();
  59.  
  60. /*//////////////////////////////////////////////////////////////////////*/
  61. struct comdesc {
  62.     int    numarg;
  63.     int    haveresp;
  64.     char    *shelp;
  65.     char    *lhelp;
  66. };
  67. #define DESC(name,args,resp,shelp,lhelp) \
  68. static struct comdesc name = {args,resp,shelp,lhelp};
  69. extern struct comdesc
  70.     MMS_H_HELP,    MMS_H_QUIT;
  71.  
  72. #define NO    0
  73. #define RO    1
  74. #define WO    2
  75. #define RW    3
  76. #define XO    4
  77. #define RX    5
  78. #define WX    6
  79. #define RWX    7
  80. #define ALL    0xFF
  81.  
  82. typedef struct {
  83.     char     *mms_name;
  84.     int    (*mms_func)();
  85.     int      mms_argc;
  86.     int      mms_argbody;    /* argument body follows */
  87.     int      mms_access;    /* necessary access permission */
  88.     char     *mms_desc;
  89. } MMS_Command;
  90.  
  91. typedef struct {
  92.     MMS_Command    *commands;
  93.     char        *c_name;
  94.     int         c_done;
  95.     int         c_error;
  96.     FILE        *c_partfp;
  97.     int         c_partid;
  98.     int         c_curpartid;
  99. } MMS_Commands;
  100.  
  101.  
  102. int MMS_HELP(),      MMS_QUIT(),     MMS_USER();
  103. int MMS_ENV(),       MMS_ECHO(),     MMS_CHDIR();
  104. int MMS_ADDHEAD(),   MMS_SUBJECT();
  105. int MMS_ADDTEXT();
  106. int MMS_ENCLOSE(),   MMS_TYPES();
  107. int MMS_PRINT(),     MMS_WRITE(),    MMS_SKELETON();
  108. int MMS_VIEW(),      MMS_SHOW(),     MMS_COMMAND();
  109. int MMS_PARSE();
  110. int MMS_SEND();
  111. int MMS_SH();
  112. int MMS_BLOCK();
  113. int MMS_HENCODE(),   MMS_HDECODE();
  114.  
  115. MMS_Command MMS_main_command_set[] = {
  116.     {"# commands with mark '*' are available for you"},
  117.     {"HELP",    MMS_HELP,    1,0,NO,  "show this help"},
  118.     {"QUIT",    MMS_QUIT,    1,0,NO,  "quit"},
  119.     {"USER",    MMS_USER,    3,0,NO,  "set effective user ID"},
  120.     {"ENV",    MMS_ENV,     1,0,RO,  "get/set environment"},
  121.     {"ECHO",    MMS_ECHO,    1,0,NO,  "echo given string"},
  122.     {"CHDIR",   MMS_CHDIR,   1,0,RX,  "change working directory"},
  123.     {"ADDHEAD",    MMS_ADDHEAD, 2,0,RO,  "add to To/Cc list"},
  124.     {"SUBJECT",    MMS_SUBJECT, 1,0,NO,  "set the subject"},
  125.     {"ADDTEXT",    MMS_ADDTEXT, 1,1,NO,  "add text to the body"},
  126.     {"ENCLOSE",    MMS_ENCLOSE, 1,1,RW,  "enclose nontext body"},
  127.     {"TYPES",    MMS_TYPES,   0,0,NO,  "list available content-types"},
  128.     {"PRINT",    MMS_PRINT,   0,0,NO,  "print the current message"},
  129.     {"WRITE",    MMS_WRITE,   0,0,WO,  "write the the current message to file"},
  130.     {"SKELETON",MMS_SKELETON,0,0,NO,  "print the skeleton of the message"},
  131.     {"VIEW",    MMS_VIEW,    0,0,RWX, "interpret with the Metamail"},
  132.     {"COMMAND",    MMS_COMMAND, 0,1,RO,  "get commands for the content-type"},
  133.     {"SHOW",    MMS_SHOW,    0,1,RWX, "display it"},
  134.     {"PARSE",    MMS_PARSE,   0,0,NO,  "enter PARSE subcommands"},
  135.     {"SEND",    MMS_SEND,    0,0,RWX, "send the message"},
  136.     {"HENCODE",    MMS_HENCODE, 0,0,NO,  "encode MIME header"},
  137.     {"HDECODE",    MMS_HDECODE, 0,0,NO,  "decode MIME header"},
  138.     {"SH",    MMS_SH,         1,0,RWX, "sh (for debug)"},
  139.     {"BLOCK",    MMS_BLOCK,   0,0,RWX, "command sequence"},
  140.     {"# Direct comments to <ysato@etl.go.jp>"},
  141.     0
  142. };
  143. MMS_Commands MMS_main_command_env = { MMS_main_command_set, "MAIN" };
  144.  
  145.  
  146. struct {
  147.     int    (*mmc_func)();
  148.     char     *mmc_args;
  149. } MMS_args[] = {
  150.     {MMS_ENCLOSE,    "content-type file-name"},
  151.     0
  152. };
  153.  
  154. int MMS_P_PRINT();
  155. int MMS_P_VIEW();
  156. int MMS_P_CHILD();
  157. int MMS_P_NEXT();
  158. int MMS_P_PREV();
  159. int MMS_P_PARENT();
  160.  
  161. MMS_Command MMS_PARSE_command_set[] = {
  162.     {"# PARSE subcommands:"},
  163.     {"HELP",    MMS_HELP,    1,0,NO,  "show this help"},
  164.     {"QUIT",    MMS_QUIT,    1,0,NO,  "quit PARSE command mode"},
  165.     {"PRINT",    MMS_P_PRINT, 1,0,NO,  "print current part as is"},
  166.     {"VIEW",    MMS_P_VIEW,  1,0,NO,  "view current part"},
  167.     {"CHILD",   MMS_P_CHILD, 1,0,NO,  "goto child part"},
  168.     {"PARENT",    MMS_P_PARENT,1,0,NO,  "goto parent part"},
  169.     {"NEXT",    MMS_P_NEXT,  1,0,NO,  "goto next part"},
  170.     {"PREV",    MMS_P_PREV,  1,0,NO,  "goto previous part"},
  171.     0
  172. };
  173. MMS_Commands MMS_PARSE_command_env = { MMS_PARSE_command_set, "PARSE" };
  174.  
  175. /*////////////////////////////////////////////////////////////////////////
  176.  *    Response status codes
  177.  */
  178. #define OK_GOODBYE    205
  179. #define OK_ARTICLE    220
  180. #define OK_POSTED    240
  181.  
  182. #define OK_START    200
  183. int MMS_OK_ACCESS =    201;
  184. #define OK_CMD        290
  185. #define OK_ADDHEAD    291
  186. #define OK_ADDCC    292
  187. #define OK_SUBJECT    293
  188. #define OK_ADDTEXT    294
  189. #define OK_ENCLOSE    296
  190. #define OK_VIEW        297
  191. #define OK_CONTENTTYPE    298
  192.  
  193. #define CONT_INPUT    390
  194.  
  195. int MMS_ERR_CMDSYN =    500;
  196. #define ERR_UNSUPPORTED 501
  197. #define ERR_CMD        590
  198. int MMS_ERR_ACCESS =    591;
  199. #define ERR_CONTENTTYPE    592
  200. #define ERR_INFILE    593
  201. #define ERR_TEMPFILE    594
  202. #define ERR_CONT_INPUT    596
  203.  
  204.  
  205. static
  206. mms_statusX(response_type,code,form,a,b,c,d){
  207.     printf("%d %c ",code,response_type);
  208.     if( code == MMS_ERR_CMDSYN )
  209.         printf("Usage: ");
  210.     printf(form,a,b,c,d);
  211.     printf("\n");
  212.     fflush(stdout);
  213. }
  214. MMS_status0(code,form,a,b,c,d){
  215.     mms_statusX('0',code,form,a,b,c,d);
  216. }
  217. MMS_statusI(code,form,a,b,c,d){
  218.     mms_statusX('I');
  219. }
  220. MMS_statusN(code,form,a,b,c,d){
  221.     mms_statusX('N',code,form,a,b,c,d);
  222. }
  223. MMS_statusB(code,form,a,b,c,d){
  224.     mms_statusX('B',code,form,a,b,c,d);
  225. }
  226. MMS_response(form,a,b,c,d) char *form,*a,*b,*c,*d; {
  227.     if(form[0] == '.' && form[1] == '\n')
  228.         printf("..\n");
  229.     else    printf(form,a,b,c,d);
  230.     fflush(stdout);
  231. }
  232. MMS_response_done(){
  233.     printf(".\n");
  234.     fflush(stdout);
  235. }
  236.  
  237. /*////////////////////////////////////////////////////////////////////////
  238.  */
  239.  
  240. extern char *MMS_versionNO;
  241. extern char *MMS_versionDate;
  242. char *MMS_start_message = "MetaMail Server version MMS-%s (%s)";
  243.  
  244. MMS_start_server(){
  245.     int access;
  246.     char msg[256];
  247.  
  248.     access = setup_access();
  249.     sprintf(msg,MMS_start_message,MMS_versionNO,MMS_versionDate);
  250.     MMS_status0(OK_START,"%s @%s ACCESS=%x",msg,HostName(),access);
  251.     MMS_mailtoSetup();
  252. }
  253. MMS_server_interpreter(in)
  254.     FILE *in;
  255. {
  256.     if( in != stdin )
  257.         *stdin = *in;
  258.     return MetaMetamail(&MMS_main_command_env);
  259. }
  260.  
  261. MMS_server(ac,av)
  262.     char *av[];
  263. {
  264.     MMS_start_server();
  265.     return MMS_server_interpreter(stdin);
  266. }
  267.  
  268. MetaMetamail(comenv)
  269.     MMS_Commands *comenv;
  270. {    char LineBuf[MAXPATHLEN],Command[MAXPATHLEN],ArgList[MAXPATHLEN];
  271.     int ci,sargc;
  272.     char *name;
  273.     int (*func)();
  274.  
  275.     comenv->c_done = 0;
  276.     while( MMS_getline(LineBuf,sizeof(LineBuf),MMS_COMMANDIN) != NULL ){
  277.         if( *LineBuf == 0 )
  278.             continue;
  279.  
  280.         *ArgList = 0;
  281.         sargc = sscanf(LineBuf,"%s %[^\177]",Command,ArgList);
  282.         if( sargc == 0 )
  283.             continue;
  284.  
  285.         MMS_touppers(Command);
  286.         for(ci = 0; name = comenv->commands[ci].mms_name; ci++)
  287.             if( strcmp(Command,name) == 0 ){
  288.             if( !permitted(comenv,ci) ){
  289.                 MMS_status0(MMS_ERR_ACCESS,
  290.                     "You must do USER first.");
  291.             }else{
  292.                 func = comenv->commands[ci].mms_func;
  293.  
  294.                 if( func == 0 )
  295.     MMS_status0(ERR_UNSUPPORTED,"%s not supported yet.",Command);
  296.                 else    (*func)(comenv,ArgList);
  297.                 if( comenv->c_done )
  298.                     goto done;
  299.             }
  300.             break;
  301.             }
  302.         if( name == 0 )
  303.             MMS_status0(MMS_ERR_CMDSYN,"Invalid command(%s).",
  304.                 Command);
  305.     }
  306. done:
  307.     return 0;
  308. }
  309.  
  310.  
  311. /*////////////////////////////////////////////////////////////////////////
  312.  *    PARSE command mode
  313.  */
  314. MMS_PARSE(_){
  315.     FILE *fp;
  316.     char file[MAXPATHLEN];
  317.  
  318.     *file = 0;
  319.     if( fp = MMS_synthWriteFile(file,0,0) ){
  320.         MMS_PARSE_command_env.c_partfp = fp;
  321.         MMS_PARSE_command_env.c_curpartid =
  322.         MMS_PARSE_command_env.c_partid = MMS_parser(fp,stdout);
  323.         MMS_status0(OK_CMD,"PARSE command mode");
  324.         MetaMetamail(&MMS_PARSE_command_env);
  325.                 unlink(file);
  326.     }else    MMS_status0(ERR_CMD,"cannot open tempfile.");
  327. }
  328. MMS_P_NEXT(comenv)
  329.     MMS_Commands *comenv;
  330. {    int npartid;
  331.  
  332.     if( npartid = MMS_partNext(comenv->c_curpartid) ){
  333.         comenv->c_curpartid = npartid;
  334.         MMS_status0(OK_CMD,"partid=%d",npartid);
  335.     }else    MMS_status0(ERR_CMD,"no more next.");
  336. }
  337. MMS_P_PREV(comenv)
  338.     MMS_Commands *comenv;
  339. {    int npartid;
  340.  
  341.     if( npartid = MMS_partPrev(comenv->c_curpartid) ){
  342.         comenv->c_curpartid = npartid;
  343.         MMS_status0(OK_CMD,"partid=%d",npartid);
  344.     }else    MMS_status0(ERR_CMD,"no more previous.");
  345. }
  346. MMS_P_CHILD(comenv)
  347.     MMS_Commands *comenv;
  348. {    int npartid;
  349.  
  350.     if( npartid = MMS_part1stChild(comenv->c_curpartid) ){
  351.         comenv->c_curpartid = npartid;
  352.         MMS_status0(OK_CMD,"partid=%d",npartid);
  353.     }else    MMS_status0(ERR_CMD,"no children.");
  354. }
  355. MMS_P_PARENT(comenv)
  356.     MMS_Commands *comenv;
  357. {    int npartid;
  358.  
  359.     if( npartid = MMS_partParent(comenv->c_curpartid) ){
  360.         comenv->c_curpartid = npartid;
  361.         MMS_status0(OK_CMD,"partid=%d",npartid);
  362.     }else    MMS_status0(ERR_CMD,"no parent.");
  363. }
  364. MMS_P_PRINT(comenv)
  365.     MMS_Commands *comenv;
  366. {    int partid;
  367.  
  368.     partid = comenv->c_curpartid;
  369.     MMS_statusN(OK_CMD,"body of partid=%d follows:",partid);
  370.     MMS_viewAsis(comenv->c_partfp,stdout,partid,3);
  371.     MMS_response_done();
  372. }
  373. MMS_P_VIEW(comenv)
  374.     MMS_Commands *comenv;
  375. {
  376.     MMS_putenv("MM_NOASK","1");
  377.     MMS_putenv("MM_NOTTY","1");
  378.     MMS_statusN(OK_CMD,"body of partid=%d follows:",comenv->c_curpartid);
  379.     MMS_viewCocked(comenv->c_partfp,stdout,comenv->c_curpartid);
  380.     MMS_response_done();
  381. }
  382.  
  383. /*////////////////////////////////////////////////////////////////////////
  384.  */
  385. MMS_USER(_,user_file_passwd)
  386.     char *user_file_passwd;
  387. {    char user[MAXPATHLEN],file[MAXPATHLEN],passwd[MAXPATHLEN];
  388.     char errmsg[MAXPATHLEN];
  389.     struct passwd *pw;
  390.     int uid;
  391.  
  392.     if(sscanf(user_file_passwd,"%s %s %[^\n]",user,file,passwd) != 3){
  393.         MMS_status0(MMS_ERR_CMDSYN,"USER username filename passwd");
  394.         return 0;
  395.     }
  396.     pw = MMS_user(user,file,passwd,errmsg);
  397.     if( pw == 0 ){
  398.         MMS_status0(MMS_ERR_ACCESS,"%s",errmsg);
  399.                 return 0;
  400.     }
  401.     MMS_ACCESS = ALL;
  402.  
  403.     MMS_status0(MMS_OK_ACCESS,"Cirtainly, you are %s",user);
  404.  
  405.     MMS_putenv("USER","%s",user);
  406.     MMS_putenv("HOME","%s",pw->pw_dir);
  407.     MMS_putenv("PATH","%s",
  408.         "/usr/ucb:/bin:/usr/bin:/usr/local/bin:/usr/bin/X11");
  409.     MMS_putenv("DISPLAY","%s:0",HostName());
  410.     MMS_mailtoReSetup();
  411. }
  412.  
  413. static permitted(comenv,ci)
  414.     MMS_Commands *comenv;
  415. {    int i,mask;
  416.  
  417.     for(i = 0; i < 32; i++){
  418.         mask = 1 << i;
  419.         if( mask & comenv->commands[ci].mms_access )
  420.         if((mask & MMS_ACCESS) == 0)
  421.             return 0;
  422.     }
  423.     return 1;
  424. }
  425. static setup_access(){
  426.     if( MMS_privileged_user(geteuid(),getegid()) )
  427.         return MMS_ACCESS = NO;
  428.     else    return MMS_ACCESS = RWX;
  429. }
  430.  
  431. /*////////////////////////////////////////////////////////////////////////
  432.  */
  433. DESC(MMS_H_HELP,0,0,"show this help",0);
  434. MMS_HELP(comenv,arg)
  435.     MMS_Commands *comenv;
  436.     char *arg;
  437. {    int ci,col,long_form;
  438.     char *name,*mark;
  439.  
  440.     MMS_statusN(OK_CMD,"This server accepts the following commands:");
  441.  
  442.     long_form = *arg != 0;
  443.     col = 0;
  444.  
  445.     for(ci = 0; name = comenv->commands[ci].mms_name; ci++){
  446.         if( *name == '#' ){
  447.             if( !long_form && col != 0 ){
  448.                 printf("\n");
  449.                 col = 0;
  450.             }
  451.             MMS_response("%s\n",name);
  452.         }else{
  453.             mark = permitted(comenv,ci)?"*":" ";
  454.             MMS_response("%s%-10s ",mark,name);
  455.             col += 12;
  456.  
  457.             if( long_form )
  458.                 printf("%s\n",comenv->commands[ci].mms_desc);
  459.             else{
  460.                 if( 72 <= col ){
  461.                     printf("\n");
  462.                     col = 0;
  463.                 }
  464.             }
  465.         }
  466.     }
  467.     if( !long_form ){
  468.         if( col != 0 )
  469.             MMS_response("\n");
  470.         MMS_response("# enter HELP LONG to get more help.\n");
  471.     }
  472.     MMS_response_done();
  473. }
  474.  
  475. DESC(MMS_H_QUIT,0,0,"quit",0);
  476. MMS_QUIT(mce) MMS_Commands *mce; {
  477.     if( mce == &MMS_main_command_env )
  478.         MMS_status0(OK_GOODBYE,"closing connection.  Goodbye.");
  479.     else    MMS_status0(OK_CMD,"%s command mode done.",mce->c_name);
  480.     mce->c_done = 1;
  481. }
  482.  
  483. MMS_PRINT(_){
  484.     MMS_statusN(OK_ARTICLE,"Current content of article follows:");
  485.     MMS_synthWriteFile(0,0,0);
  486.     MMS_response("\n");
  487.     MMS_response_done();
  488. }
  489.  
  490. MMS_WRITE(_,file) char *file; {
  491.     int size;
  492.  
  493.     if( *file == 0 ){
  494.         MMS_status0(MMS_ERR_CMDSYN,"WRITE filenmae");
  495.     }else{
  496.         char filebuf[MAXPATHLEN];
  497.  
  498.         if( *file != '/' ){
  499.             getwd(filebuf);
  500.             sprintf(filebuf+strlen(filebuf),"/%s",file);
  501.             file = filebuf;
  502.         }
  503.         MMS_synthWriteFile(file,&size,1);
  504.         if( 0 < size )
  505.             MMS_status0(OK_CMD,"%d bytes written to %s",size,file);
  506.         else    MMS_status0(ERR_CMD,"cannot write to %s",file);
  507.     }
  508. }
  509. MMS_SKELETON(_){
  510.     FILE *fp;
  511.     char file[MAXPATHLEN];
  512.     int rootid;
  513.  
  514.     *file = 0;
  515.     if( fp = MMS_synthWriteFile(file,0,0) ){
  516.         rootid = MMS_parser(fp,stdout);
  517.         MMS_statusN(OK_CMD,"skeleton of the message follows:");
  518.         MMS_viewSkeleton(fp,stdout,rootid);
  519.         MMS_response_done();
  520.         unlink(file);
  521.     }else    MMS_status0(ERR_CMD,"cannot open tempfile.");
  522. }
  523. MMS_VIEW(_){
  524.     static char *av[4] = {"metamail","-z",0};
  525.     char file[2048];
  526.     FILE *fp;
  527.     char command[1024];
  528.  
  529.     *file = 0;
  530.     fp = MMS_synthWriteFile(file,0,0);
  531.     if( fp == NULL ){
  532.         MMS_status0(ERR_TEMPFILE,"cant create temporary file.");
  533.         return NULL;
  534.     }
  535.     fclose(fp);
  536.     av[2] = file;
  537.  
  538.     MMS_putenv("MM_NOASK","1");
  539.     MMS_putenv("MM_NOTTY","1");
  540.     MMS_statusN(OK_VIEW,"view start.");
  541.     sprintf(command,"exec %s -z %s","/usr/local/bin/metamail",file);
  542.  
  543.     if( vfork() == 0 ){
  544.         system(command);
  545.         _exit(0);
  546.     }
  547.     wait(0);
  548.     unlink(file);
  549.  
  550. printf("\n");
  551.     MMS_response_done();
  552. }
  553.  
  554. MMS_SHOW(_,type)
  555.     char *type;
  556. {    FILE *body,*player;
  557.     char command[MAXPATHLEN];
  558.     int bytes;
  559.     void (*osig)();
  560.  
  561.     if( strcasecmp(type,"audio/basic") == 0 )
  562.         sprintf(command,"cat > /dev/audio");
  563.     else
  564.     if( strcasecmp(type,"image/xwd") == 0 )
  565.         sprintf(command,"xloadimage stdin");
  566.     else{
  567.         MMS_status0(ERR_CONT_INPUT,
  568.             "unsupported type [%s] cannot display",type);
  569.         return;
  570.     }
  571.  
  572.     player = popen(command,"w");
  573.     if( player == NULL ){
  574.         MMS_status0(ERR_CONT_INPUT,"cannot exec %s",command);
  575.         return;
  576.     }
  577.     MMS_status0(CONT_INPUT,"send data in BASE64 coding:");
  578.     MMS_statusN(OK_CMD,"showing...");
  579.  
  580.     osig = signal(SIGPIPE,SIG_IGN);
  581.     body = MMS_getbody(MMS_COMMANDIN,&bytes);
  582.     MMS_response("Transmission done: %d bytes.\n",bytes);
  583.     from64(body,player,0,NULL);
  584.     fclose(body);
  585.  
  586.     pclose(player);
  587.     signal(SIGPIPE,osig);
  588.  
  589.     MMS_response_done();
  590. }
  591.  
  592. MMS_COMMAND(_,ctype)
  593.     char *ctype;
  594. {    char *command;
  595.  
  596.     command = (char*)MMS_mailtoGetCommand(ctype,0);
  597.     if(command)
  598.         MMS_status0(OK_CMD, "%s",command);
  599.     else    MMS_status0(ERR_CMD,"%s","NOCOMMAND");
  600. }
  601.  
  602.  
  603. MMS_SEND(_){
  604.     char file[2048],command[2048];
  605.     FILE *fp;
  606.  
  607.     *file = 0;
  608.     fp = MMS_synthWriteFile(file,0,1);
  609.     if( fp == NULL ){
  610.         MMS_status0(ERR_TEMPFILE,"cant create temporary file");
  611.         return NULL;
  612.     }
  613.     unlink(file);
  614.  
  615.     sprintf(command,"exec /usr/lib/sendmail -t -om");
  616.     if( vfork() == 0 ){
  617.         close(0);
  618.         dup(fileno(fp));
  619.         system(command);
  620.         _exit(0);
  621.     }
  622.     wait(0);
  623.     fclose(fp);
  624.     MMS_status0(OK_POSTED,"Article posted successfully.");
  625. }
  626.  
  627. MMS_ADDHEAD(_,field_entry)
  628.     char *field_entry;
  629. {    char field[128],entry[2048],errmsg[256];
  630.  
  631.     if( sscanf(field_entry,"%s %[^\177]",field,entry) != 2 ){
  632.         MMS_status0(MMS_ERR_CMDSYN,"ADDHEAD fieldname entyr");
  633.         return 0;
  634.     }
  635.     if( MMS_synthAddHead(field,entry,errmsg) != 0 )
  636.         MMS_status0(ERR_CMD,errmsg);
  637.     else    MMS_status0(OK_ADDHEAD,"added to %s list.",field);
  638. }
  639. MMS_SUBJECT(_,subject)
  640.     char *subject;
  641. {
  642.     MMS_synthSubject(subject);
  643.     MMS_status0(OK_SUBJECT,"subject set.");
  644. }
  645.  
  646.  
  647. MMS_ADDTEXT(_,arg)
  648.     char *arg;
  649. {    char msg[2048];
  650.     int stcode,lines;
  651.  
  652.     stcode = MMS_synthToggleTextAttr(CONT_INPUT,ERR_CONT_INPUT,
  653.             "send text then end with \".\":",arg);
  654.     if( stcode == ERR_CONT_INPUT )
  655.         return;
  656.  
  657.     lines = MMS_synthAddText(MMS_COMMANDIN);
  658.     sprintf(msg,"text added (%d lines).",lines);
  659.     MMS_synthToggleTextAttr(OK_ADDTEXT,OK_ADDTEXT,msg,arg);
  660. }
  661. MMS_HDECODE(_,arg)
  662.     char *arg;
  663. {    FILE *tmp;
  664.     char line[256];
  665.  
  666.     MMS_status0(CONT_INPUT,"send header.");
  667.     tmp = tmpfile();
  668.     while( MMS_getline(line,sizeof(line),MMS_COMMANDIN) != NULL ){
  669.         fputs(line,tmp);
  670.         fputs("\n",tmp);
  671.     }
  672.     fseek(tmp,0,0);
  673.  
  674.     MMS_status0(OK_CMD,"decoded message follows:");
  675.     MIME_headerDecode(tmp,stdout,1);
  676.     MMS_response_done();
  677.     fclose(tmp);
  678. }
  679. MMS_HENCODE(_,arg)
  680.     char *arg;
  681. {    FILE *tmp;
  682.     char line[256];
  683.  
  684.     MMS_status0(CONT_INPUT,"send header.");
  685.     tmp = tmpfile();
  686.     while( MMS_getline(line,sizeof(line),MMS_COMMANDIN) != NULL ){
  687.         fputs(line,tmp);
  688.         fputs("\n",tmp);
  689.     }
  690.     fseek(tmp,0,0);
  691.  
  692.     MMS_status0(OK_CMD,"encoded message follows:");
  693.     MIME_headerEncode(tmp,stdout);
  694.     MMS_response_done();
  695.     fclose(tmp);
  696. }
  697.  
  698. MMS_ENCLOSE(_,args)
  699.     char *args;
  700. {    int mailpart;
  701.     char ctype[2048],file[2048],errmsg[256];
  702.     FILE *body,*ifp;
  703.     int bytes;
  704.  
  705.     file[0] = 0;
  706.     if( sscanf(args,"%s %s",ctype,file) < 1 ){
  707.         MMS_status0(MMS_ERR_CMDSYN,"ENCLOSE content-type [filename]");
  708.         return MMS_ERR_CMDSYN;
  709.     }
  710.     if( !MMS_mailtoAvailableCtype(ctype) ){
  711.         MMS_status0(ERR_CONTENTTYPE,"unknown content-type: %s",ctype);
  712.         return ERR_CONTENTTYPE;
  713.     }
  714.  
  715.     if( file[0] ){
  716.         ifp = fopen(file,"r");
  717.         if( ifp == NULL ){
  718.             MMS_status0(ERR_INFILE,"can't open file: %s",file);
  719.             return 0;
  720.         }
  721.     }else{
  722.         MMS_status0(CONT_INPUT,"send data in BASE64 coding:");
  723.         ifp = tmpfile();
  724.         body = MMS_getbody(MMS_COMMANDIN,&bytes);
  725.         from64(body,ifp,0,NULL);
  726.         fclose(body);
  727.         MMS_fseek(ifp,0,0);
  728.         sprintf(file,"INPUT(%d bytes)",bytes);
  729.     }
  730.         if( mailpart = MMS_synthEncloseFile(ctype,ifp,errmsg) ){
  731.                 MMS_statusN(OK_ENCLOSE,"%s enclosed as %s",file,ctype);
  732.                 MMS_synthAddPart(mailpart);
  733.                 MMS_response_done();
  734.         }else{
  735.         MMS_status0(ERR_CMD,"%s",errmsg);
  736.     }
  737.     fclose(ifp);
  738. }
  739.  
  740. MMS_TYPES(_){
  741.     MMS_statusN(OK_CONTENTTYPE,"known content-types:");
  742.     MMS_mailtoPrintTypes(stdout);
  743.     MMS_response_done();
  744. }
  745.  
  746. /*////////////////////////////////////////////////////////////////////////
  747.  *    MISC
  748.  */
  749.  
  750. extern char **environ;
  751. MMS_ENV(_,envarg)
  752.     char *envarg;
  753. {    char name[1024],body[4096];
  754.     char *oldenv;
  755.     int sc,envi;
  756.  
  757.     sc = sscanf(envarg,"%s %[^\177]",name,body);
  758.     switch(sc){
  759.         default:
  760.         case 0:    MMS_statusN(OK_CMD,"environments follow:");
  761.             for(envi = 0; environ[envi]; envi++)
  762.                 MMS_response("%s\n",environ[envi]);
  763.             MMS_response_done();
  764.             break;
  765.         case 1:
  766.             if( oldenv = getenv(name) )
  767.                 MMS_status0(OK_CMD,"%s=%s",name,oldenv);
  768.             else    MMS_status0(OK_CMD,"%s undefined.",name);
  769.             break;
  770.         case 2:
  771.             oldenv = getenv(name);
  772.             MMS_putenv(name,"%s",body);
  773.             MMS_status0(OK_CMD,"env %s",oldenv?"reset":"set");
  774.     }
  775. }
  776. MMS_ECHO(_,string)
  777.     char *string;
  778. {
  779.     MMS_status0(OK_CMD,"%s",string);
  780. }
  781. MMS_SH(_,com){
  782.     MMS_statusN(OK_CMD,"START %s",com);
  783.     system(com);
  784.     MMS_response_done();
  785. }
  786.  
  787. MMS_CHDIR(_,dir)
  788.     char *dir;
  789. {    char wd[2048];
  790.  
  791.     if( chdir(dir) == 0 ){
  792.         getwd(wd);
  793.         MMS_status0(OK_CMD, "ok. %s",wd);
  794.     }else    MMS_status0(ERR_CMD,"cant go to %s",dir);
  795. }
  796.  
  797. MMS_BLOCK(_,arg)
  798.     char *arg;
  799. {
  800. }
  801.